// Ninf-G-XX, ver. 0.1
// Copyright 2011 National Institute of Advanced Industrial Science and Technology
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _PROTOCOL_HH_
#define _PROTOCOL_HH_

#include <string>
#include <list>

#include "Credential.hh"

/**/
class ProtocolError : public std::exception {
public:
  std::string message;

  virtual ~ProtocolError() throw(){}
  ProtocolError():message("Protocol initialization error."){}
  ProtocolError(const std::string & mes):message(mes){}

};


/// this is the base abstract class for all the
/// Protocol classes.
class Protocol {
private:
  std::list<std::string> names;
public:
  /* Simple constructor which only takes the protocol name as
     parameter:
     For example "ftp", "http", "ibp", etc.
   */
  Protocol(const std::string& name);

  /*
   * No argument Constructor for default
   */
  Protocol(){}

  /* A simple copy constructor. */
  Protocol(const Protocol& protocol);

  /* Operator "=" overload. */
  Protocol& operator=(const Protocol& protocol);

  virtual ~Protocol();

  /**
     getNames() it does not modify the object.
   */
  std::list<std::string> getNames() const;

  void addName(const std::string& name);

  /* To download a file using this protocol.
     Here the function only takes two arguments, only one
     source URI and a Credential object to access the data.
   */
  virtual void downloadDataFile(const std::string& sourceURI,
                           const Credential& credential) = 0;
  /* Here, the user can choose the destination path for the
     downloaded file.
   */
  virtual void downloadDataFile(const std::string& sourceURI,
                           const std::string& path,
                           const Credential& credential) = 0;
  /* We can now use more than only one source.
     For each of them, we use a Credential object to access the data.
   */
  virtual void downloadDataFile(const std::list<std::string>& sourceURIs,
                           const std::list<Credential>& credentials) = 0;
  /* The same with choosing the destination path.
   */
  virtual void downloadDataFile(const std::list<std::string>& sourceURIs,
                           const std::string& path,
                           const std::list<Credential>& credentials) = 0;

  /* To download a data and load it into memory.
     Here the user allocated the memory to store the data.
   */
  virtual void downloadDataMemory(const std::string& sourceURI,
                           void* const dest,
                           const Credential& credential=Credential()) = 0;
  /* Here the user does not allocate the memory. The pointer to
     the data is stored inside the "dest" parameter.
   */
  virtual void downloadDataMemory(const std::string& sourceURI,
                           void** dest,
                           size_t* size,
                           const Credential& credential=Credential()) = 0;

  /* The same functions with more than one data source. */
  virtual void downloadDataMemory(const std::list<std::string>& sourceURIs,
                           void* const dest,
                           const std::list<Credential>& credentials) = 0;
  virtual void downloadDataMemory(const std::list<std::string>& sourceURIs,
                           void** dest,
                           size_t* size,
                           const std::list<Credential>& credentials) = 0;

  /**
   * deleting data stored at the specified location
   */

  virtual void deleteData(const std::string & URI,
                          const Credential& credential=Credential()) {
    throw ProtocolError("Unsupported");
  }

  virtual void deleteData(const std::list<std::string>& sourceURIs,
                        const std::list<Credential>& credentials) {
    throw ProtocolError("Unsupported");
  }

  /* To upload a data file. The credential is used to access
     the server.
   */
  virtual void uploadDataFile(const std::string& destinationURI,
                           const std::string& path,

                           const Credential& credential) = 0;

  /* To upload a memory data. The credential is used to access
      the server.
   */
  virtual void uploadDataMemory(const std::string& destinationURI,
                           void* const src,
                           size_t      src_size,
                           const Credential& credential=Credential()) = 0;
};


#endif
